const express = require("express");
const util = require("../common/util");
const WarehouseZoneDB = require("../model/db/warehousezone");

/**
 * 获取指定ID的仓库区域
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应
 */
async function find(req, res) {
  try {
    const db = WarehouseZoneDB.getInstance();
    const zoneId = parseInt(req.params.id, 10); // 验证ID是否为数字

    if (isNaN(zoneId)) {
      throw new Error("ID必须是一个数字");
    }

    const zone = await db.find(zoneId);

    if (!zone) {
      res.status(404).json(util.FormatJSONData(404, "仓库区域不存在", {}));
      return;
    }

    util.logFormat(`获取【${zoneId}】仓库区域信息：%O`, zone);
    res.json(util.FormatJSONData(200, "获取仓库区域信息成功", zone));
  } catch (error) {
    util.err(error);
    res.status(500).json(util.FormatJSONData(500, "服务器内部错误", error.message));
  }
}

/**
 * 查找仓库区域列表
 */
async function findAll(req, res) {
  try {
    const db = WarehouseZoneDB.getInstance();

    // 尝试从请求中获取limit和offset，并确保它们是有效的数字  
    let limit = parseInt(req.query.limit, 10);
    if (isNaN(limit) || limit < 0) {
      // 设置一个默认值或者抛出一个错误  
      limit = 10; // 或者设置为-1，这取决于你的数据访问层如何处理-1  
    }

    let offset = parseInt(req.query.offset, 10);
    if (isNaN(offset) || offset < 0) {
      // 设置一个默认值或者抛出一个错误  
      offset = 0; // 通常偏移从0开始  
    }

    // 调用数据访问层的方法  
    const result = await db.findAll(limit, offset);


    // 假设db.findAll返回的是一个包含rows和可能还有其他字段的对象  
    if (result) {
      // 返回成功的响应  
      res.json(util.FormatJSONData(200, "获取仓库区域的货架列表成功", result));
    } else {
      // 如果没有找到任何结果，你可能想要返回一个不同的状态码或消息  
      res.status(404).json(util.FormatJSONData(404, "未找到仓库区域的货架列表", {}));
    }
  } catch (error) {
    // 捕获并处理错误  
    util.err(error);
    res.status(500).json(util.FormatJSONData(500, "服务器内部错误", error.message));
  }
}

/**  
 * 查找含有货架最少的仓库区域列表  
 */  
async function findMinShelves(req, res) {  
  try {  
    const db = WarehouseZoneDB.getInstance();  
  
    // 尝试从请求中获取limit和offset，但在这个场景下，limit更可能是限制结果数量  
    // 而不是限制货架数量（因为货架数量是由查询本身确定的）  
    let limit = parseInt(req.query.limit, 10) || 10; // 默认为10，或者您可以根据需求设置  
    let offset = parseInt(req.query.offset, 10) || 0; // 偏移量通常从0开始  
  
    // 调用数据访问层的新方法  
    const result = await db.findMinShelves(limit, offset);  
  
    // 假设db.findWarehouseZonesWithLeastShelves返回的是一个包含rows的数组  
    if (result) {  
      // 返回成功的响应，包含仓库区域列表  
      res.json(util.FormatJSONData(200, "获取含有货架最少的仓库区域列表成功", result));  
    } else {  
      // 如果没有找到任何结果，返回一个空列表  
      res.json(util.FormatJSONData(200, "未找到含有货架的仓库区域", []));  
    }  
  } catch (error) {  
    // 捕获并处理错误  
    util.err(error);  
    res.status(500).json(util.FormatJSONData(500, "服务器内部错误", error.message));  
  }  
}

/**    
 * 查找与指定仓库区域名字匹配的货架列表    
 */
async function findShelvesByZoneName(req, res) {
  try {
    const db = WarehouseZoneDB.getInstance();
    // 尝试从请求中获取zoneName    
    const name = req.query.name; // 假设zoneName是通过查询参数传递的，例如 /shelves?zoneName=storage  
    if (!name || typeof name !== 'string') {
      // 如果zoneName不存在或不是有效的字符串，返回一个错误响应    
      res.status(400).json(util.FormatJSONData(400, "请提供有效的仓库区域名字", {}));
      return;
    }

    // 尝试从请求中获取limit和offset，并确保它们是有效的数字  
    let limit = parseInt(req.query.limit, 10);
    if (isNaN(limit) || limit < 0) {
      // 设置一个默认值或者抛出一个错误  
      limit = 10; // 或者设置为-1，这取决于你的数据访问层如何处理-1  
    }

    let offset = parseInt(req.query.offset, 10);
    if (isNaN(offset) || offset < 0) {
      // 设置一个默认值或者抛出一个错误  
      offset = 0; // 通常偏移从0开始  
    }
    // 在SQL中使用LIKE来进行模糊查询  
    // 注意：这里使用了%作为通配符，它匹配任意数量的字符    
    const result = await db.findShelvesByZoneName(name, limit, offset);
    // 假设db.query返回的是一个包含rows和可能还有其他字段的对象  
    if (result) {
      // 返回成功的响应  
      res.json(util.FormatJSONData(200, "获取与指定仓库区域名字匹配的货架列表成功", result));
    } else {
      // 如果没有找到任何结果，返回一个不同的状态码或消息  
      res.status(404).json(util.FormatJSONData(404, "未找到与指定仓库区域名字匹配的货架列表", {}));
    }
  } catch (error) {
    // 捕获并处理错误  
    util.err(error);
    res.status(500).json(util.FormatJSONData(500, "服务器内部错误", error.message));
  }
}

/**  
* 根据仓库区域内类型模糊查询仓库区域  
* @param {express.Request} req 请求  
* @param {express.Response} res 响应  
*/
async function findByZoneTypeLike(req, res) {
  try {
    const db = WarehouseZoneDB.getInstance();
    const zoneType = req.query.zoneType; // 假设通过查询参数传递仓库区域名称  

    if (!zoneType || zoneType.trim() === '') {
      throw new Error("仓库区域名称不能为空");
    }

    // 使用LIKE操作符实现模糊查询  
    const zone = await db.findByZoneTypeLike(zoneType);

    if (!zone || zone.length === 0) {
      res.status(404).json(util.FormatJSONData(404, "未找到匹配的仓库区域", {}));
      return;
    }

    // 假设db.findByName返回的是一个数组，因为可能有多个匹配的仓库区域  
    util.logFormat(`找到匹配的仓库区域信息：%O`, zone);
    res.json(util.FormatJSONData(200, "获取仓库区域信息成功", zone));
  } catch (error) {
    util.err(error);
    res.status(500).json(util.FormatJSONData(500, "服务器内部错误", error.message));
  }
}

/**  
* 根据仓库区域内名字模糊查询仓库区域  
* @param {express.Request} req 请求  
* @param {express.Response} res 响应  
*/
async function findByKeyword(req, res) {
  try {
    const db = WarehouseZoneDB.getInstance();
    const name = req.query.name; // 假设通过查询参数传递仓库区域名字  
    const limit = req.query.limit; // 默认限制为10条记录  
    const offset = req.query.offset; // 默认偏移为0  

    if (!name || name.trim() === '') {
      throw new Error("仓库区域类型不能为空");
    }

    // 使用LIKE操作符实现模糊查询，并传入limit和offset进行分页  
    const zone = await db.findByKeyword(name, limit, offset);
    console.log(zone);

    if (!zone) {
      res.status(404).json(util.FormatJSONData(404, "未找到匹配的仓库区域", {}));
      return;
    }

    // 假设db.findByKeywordWithPagination返回的是一个数组，因为可能有多个匹配的仓库区域  
    util.logFormat(`找到匹配的仓库区域信息：%O`, zone);
    res.json(util.FormatJSONData(200, "获取仓库区域信息成功", zone));
  } catch (error) {
    util.err(error);
    res.status(500).json(util.FormatJSONData(500, "服务器内部错误", error.message));
  }
}

/**
 * 添加仓库区域
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应
 */
async function add(req, res) {
  try {
    const zone = {
      warehouseId: req.body.warehouseId,
      name: req.body.name,
      capacity: req.body.capacity,
      occupiedSpace: req.body.occupiedSpace,
      zoneType: req.body.zoneType,
      zoneManagerId: req.body.zoneManagerId,
      locationGuide: req.body.locationGuide,
      safetyStockLevel: req.body.safetyStockLevel,
      lastAuditDate: new Date(),
      comments: req.body.comments
    };

    // 数据验证
    if (typeof zone.name !== "string" || zone.name.trim() === "") {
      throw new Error("名称不能为空或仅包含空格");
    }
    if (typeof zone.capacity !== "number" || zone.capacity <= 0) {
      throw new Error("容量必须是一个正数");
    }

    const db = WarehouseZoneDB.getInstance();
    const newZone = await db.add(zone);

    util.log(`添加仓库区域信息：newZone=%O`, newZone);
    res.json(util.FormatJSONData(201, "添加仓库区域信息成功", newZone));
  } catch (error) {
    util.err(error);
    res.status(400).json(util.FormatJSONData(400, "无效的数据", error.message));
  }
}

/**  
 * 修改仓库区域  
 * @param {express.Request} req 请求  
 * @param {express.Response} res 响应  
 */
async function update(req, res) {
  try {
    // 假设 req.params.zoneId 是要更新的仓库区域的唯一标识符  

    const zone = {
      warehouseId: req.body.warehouseId,
      name: req.body.name,
      capacity: req.body.capacity,
      occupiedSpace: req.body.occupiedSpace,
      zoneType: req.body.zoneType,
      zoneManagerId: req.body.zoneManagerId,
      locationGuide: req.body.locationGuide,
      safetyStockLevel: req.body.safetyStockLevel,
      lastAuditDate: req.body.lastAuditDate, // 在更新时通常不需要设置这个字段  
      comments: req.body.comments,
      id: req.params.id
    };

    // 数据验证  
    if (typeof zone.name !== "string" || zone.name.trim() === "") {
      throw new Error("名称不能为空或仅包含空格");
    }
    if (typeof zone.capacity !== "number" || zone.capacity <= 0) {
      throw new Error("容量必须是一个正数");  
    }

    // 假设 WarehouseZoneDB.getInstance().update 是用于更新数据库记录的方法  
    const db = WarehouseZoneDB.getInstance();
    // 这里需要传递 zoneId 和 zone 对象来更新数据库中的记录  
    const updatedZone = await db.update(zone);

    util.log(`更新仓库区域信息：updatedZone=%O`, updatedZone);
    res.json(util.FormatJSONData(200, "更新仓库区域信息成功", updatedZone));
  } catch (error) {
    util.err(error);
    res.status(400).json(util.FormatJSONData(400, "无效的数据", error.message));
  }
}
async function getCount() {
  try {
    const db = WarehouseZoneDB.getInstance();
    const count = await db.getCount();
    res.json(util.FormatJSONData(200, "获取仓库区域数量成功", count));

  } catch (err) {
    util.err(err);
    res.status(400).json(util.FormatJSONData(400, "获取仓库数量失败", err.message));
  }
}

/**
 * 删除仓库区域
 * @param {express.Request} req 请求
 * @param {express.Response} res 响应
 */
async function remove(req, res) {
  try {
    const db = WarehouseZoneDB.getInstance();
    const deletedCount = await db.remove(req.params.id);

    if (!deletedCount) {
      res.status(404).json(util.FormatJSONData(404, "仓库区域未找到", {}));
      return;
    }

    util.log(`删除仓库区域信息：deletedCount=${deletedCount}`);
    res.json(util.FormatJSONData(204, "删除仓库区域信息成功", {}));
  } catch (error) {
    util.err(error);
    res.status(500).json(util.FormatJSONData(500, "删除仓库区域失败", error.message));
  }
}

module.exports = {
  findByZoneTypeLike,
  find,
  add,
  update,
  remove,
  findByKeyword,
  findAll,
  getCount,
  findShelvesByZoneName,
  findMinShelves,
};